home *** CD-ROM | disk | FTP | other *** search
- /*
- * syncLock.c --
- *
- * These are internal locking routines of the Synchronization module.
- * These routines are slower but safer versions of the routines (found
- * in sync.h) to get and release monitor locks, and to wait on
- * and notify condition variables.
- *
- * A process is blocked by making it wait on an event. An event is
- * just an uninterpreted integer that gets 'signaled' by the routine
- * Sync_SlowBroadcast.
- *
- * Copyright 1985 Regents of the University of California
- * All rights reserved.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/sync/syncLock.c,v 9.13 92/01/06 15:19:49 kupfer Exp $ SPRITE (Berkeley)";
- #endif /* not lint */
-
- #include <sync.h>
- #include <sprite.h>
- #include <mach.h>
- #include <list.h>
- #include <syncInt.h>
- #include <sched.h>
- #include <proc.h>
- #include <timer.h>
- #include <rpc.h>
- #include <bstring.h>
-
- /*
- * A counter to record the number of busy wait loops executed
- * while trying to P a semaphore. This is incremented inside the
- * loop of MASTER_LOCK.
- */
- int sync_BusyWaits = 0;
-
- /*
- * A counter to record the number of events that had clashes on the hash.
- */
-
- int sync_Collisions = 0;
-
- /*
- * The event hash chain. Process control blocks are placed in a hash
- * chain keyed on the event that the process is waiting on.
- */
-
- #define PROC_HASHBUCKETS 63
- static List_Links eventChainHeaders[PROC_HASHBUCKETS];
-
- /*
- * Instrumentation to record the number of calls to the wakeup routine
- * and to record how many processes were woken up.
- */
-
- Sync_Instrument sync_Instrument[MACH_MAX_NUM_PROCESSORS];
- Sync_Instrument *sync_InstrumentPtr[MACH_MAX_NUM_PROCESSORS];
-
- /*
- * Statistics related to remote waiting.
- */
- int syncProcWakeupRaces = 0;
-
- static void ProcessWakeup _ARGS_((Proc_ControlBlock *procPtr, int waitToken));
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_Init --
- *
- * This initializes the event hash chain. The hash table is
- * an array of list headers.
- *
- * Instrumentation variables are also initialized.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The hash chain headers are initialized to be dummy list elements
- *
- *----------------------------------------------------------------------------
- */
- void
- Sync_Init()
- {
- register int i;
-
- for (i=0 ; i<PROC_HASHBUCKETS ; i++) {
- List_Init(&eventChainHeaders[i]);
- }
- bzero((Address) sync_Instrument, sizeof(sync_Instrument));
- for (i=0; i < MACH_MAX_NUM_PROCESSORS; i++) {
- sync_InstrumentPtr[i] = &sync_Instrument[i];
- }
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Sync_GetLock --
- *
- * This is the kernel version of the Sync_GetLock routine. The user
- * version is written in assembler, but in the kernel we want to
- * record locking statistics so we have our own version.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The type of the previous lock is added to the array of prior types.
- * The lock is added to the lock stack in the pcb.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Sync_GetLock(lockPtr)
- Sync_Lock *lockPtr;
- {
- ReturnStatus status = SUCCESS;
-
- Sync_LockRegister(lockPtr);
- if (Mach_TestAndSet(&(lockPtr->inUse)) != 0) {
- status = Sync_SlowLock(lockPtr);
- } else {
- Sync_RecordHit(lockPtr);
- Sync_StoreDbgInfo(lockPtr, FALSE);
- Sync_AddPrior(lockPtr);
- }
- return status;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Sync_Unlock--
- *
- * The kernel version of the unlock routine. We have a different
- * version from the user so we can do locking statistics.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The lock is removed from the lock stack in the pcb.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- Sync_Unlock(lockPtr)
- Sync_Lock *lockPtr;
- {
- ReturnStatus status = SUCCESS;
-
- lockPtr->inUse = 0;
- SyncDeleteCurrent(lockPtr);
- if (lockPtr->waiting) {
- status = Sync_SlowBroadcast((unsigned int)lockPtr, &lockPtr->waiting);
- }
- return status;
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_SlowLock --
- *
- * Acquire a lock while holding the synchronization master lock.
- *
- * Inside the critical section the inUse bit is checked. If we have
- * to wait the process is put to sleep waiting on an event associated
- * with the lock.
- *
- * Results:
- * SUCCESS is always returned.
- *
- * Side effects:
- * The lock is acquired when this procedure returns. The process may
- * have been put to sleep while waiting for the lock to become
- * available.
- *
- *----------------------------------------------------------------------------
- */
-
- ENTRY ReturnStatus
- Sync_SlowLock(lockPtr)
- register Sync_Lock *lockPtr;
- {
- MASTER_LOCK(sched_MutexPtr);
-
- #ifdef spur
- Mach_InstCountStart(0);
- #endif
-
- while (Mach_TestAndSet(&(lockPtr->inUse)) != 0) {
- lockPtr->waiting = TRUE;
- /*
- * Check the inUse semaphore again after setting the waiting. A zero
- * semaphore value means the lock was released after our previous
- * TestAndSet and possibly before we set the waiting flag. This test
- * prevents us from waiting if the Sync_Lock missed our waiting flag.
- */
- if (Mach_TestAndSet(&(lockPtr->inUse)) == 0) {
- break;
- }
- (void) SyncEventWaitInt((unsigned int)lockPtr, FALSE);
- Sync_RecordMiss(lockPtr);
- #ifdef spur
- Mach_InstCountEnd(1);
- #endif
- MASTER_UNLOCK(sched_MutexPtr);
- MASTER_LOCK(sched_MutexPtr);
- #ifdef spur
- Mach_InstCountStart(0);
- #endif
- }
- Sync_RecordHit(lockPtr);
- Sync_StoreDbgInfo(lockPtr, FALSE);
- Sync_AddPrior(lockPtr);
- #ifdef spur
- Mach_InstCountOff(0);
- if (Mach_InstCountIsOn(1)) {
- panic("About to unlock sched_Mutex with inst count on.\n");
- }
- #endif
- MASTER_UNLOCK(sched_MutexPtr);
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_SlowWait --
- *
- * Wait on a condition. The lock is released and the process is blocked
- * on the event. A future call to SyncSlowBroadcast will signal the
- * condition and make this process runnable again. Before returning
- * the lock is reaquired.
- *
- * This can only be called while a lock is held. This forces our
- * client to safely check global state while in a monitor.
- *
- * Results:
- * TRUE if interrupted because of signal, FALSE otherwise.
- *
- * Side effects:
- * Put the process to sleep and release the monitor lock. Other
- * processes waiting on the monitor lock become runnable.
- *
- *----------------------------------------------------------------------------
- */
-
- ENTRY Boolean
- Sync_SlowWait(conditionPtr, lockPtr, wakeIfSignal)
- Sync_Condition *conditionPtr; /* Condition to wait on. */
- register Sync_Lock *lockPtr; /* Lock to release. */
- Boolean wakeIfSignal; /* TRUE => wake if signal pending. */
- {
- Boolean sigPending;
-
- conditionPtr->waiting = TRUE;
- MASTER_LOCK(sched_MutexPtr);
- /*
- * release the monitor lock and wait on the condition
- */
- lockPtr->inUse = 0;
- lockPtr->waiting = FALSE;
- SyncDeleteCurrent(lockPtr);
- SyncEventWakeupInt((unsigned int)lockPtr);
- sigPending = SyncEventWaitInt((unsigned int) conditionPtr, wakeIfSignal);
- #ifdef spur
- Mach_InstCountEnd(1);
- #endif
- MASTER_UNLOCK(sched_MutexPtr);
-
- (void) Sync_GetLock(lockPtr);
-
- return(sigPending);
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_SlowBroadcast --
- *
- * Mark all processes waiting on an event as runable. The flag that
- * indicates there are waiters is cleared here inside the protected
- * critical section. This has "broadcast" semantics because everyone
- * waiting is made runable. We don't yet have a mechanism to wake up
- * just one waiting process.
- *
- * Results:
- * SUCCESS is always returned.
- *
- * Side effects:
- * Make processes waiting on the event runnable.
- *
- *----------------------------------------------------------------------------
- */
-
- ENTRY ReturnStatus
- Sync_SlowBroadcast(event, waitFlagPtr)
- unsigned int event;
- int *waitFlagPtr;
- {
- MASTER_LOCK(sched_MutexPtr);
-
- *waitFlagPtr = FALSE;
- SyncEventWakeupInt(event);
- #ifdef spur
- if (Mach_InstCountIsOn(1)) {
- panic("About to unlock sched_Mutex with inst count on.\n");
- }
- #endif
-
- MASTER_UNLOCK(sched_MutexPtr);
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_SlowMasterWait --
- *
- * Wait on an event. Like SyncSlowWait except that the lock that
- * is released is a master lock, not a monitor lock.
- *
- * Results:
- * TRUE if wake up because of a signal, FALSE otherwise.
- *
- * Side effects:
- * Put the process to sleep and release the master lock. Other
- * processes waiting on the monitor lock become runnable.
- *
- *
- *----------------------------------------------------------------------------
- */
-
- ENTRY Boolean
- Sync_SlowMasterWait(event, mutexPtr, wakeIfSignal)
- unsigned int event; /* Event to wait on. */
- Sync_Semaphore *mutexPtr; /* Mutex to release and reaquire. */
- Boolean wakeIfSignal; /* TRUE => wake if signal pending. */
- {
- Boolean sigPending;
-
- MASTER_LOCK(sched_MutexPtr);
-
- /*
- * release the master lock and wait on the condition
- */
- MASTER_UNLOCK(mutexPtr);
-
- sigPending = SyncEventWaitInt(event, wakeIfSignal);
-
- #ifdef spur
- Mach_InstCountEnd(1);
- #endif
-
- MASTER_UNLOCK(sched_MutexPtr);
- /*
- * re-acquire master lock before proceeding
- */
- MASTER_LOCK(mutexPtr);
-
- return(sigPending);
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_UnlockAndSwitch --
- *
- * Release the monitor lock and then perform a context switch to the
- * given state.
- *
- * Results:
- * SUCCESS is always returned.
- *
- * Side effects:
- * Context switch the process and release the monitor lock. Other
- * processes waiting on the monitor lock become runnable.
- *
- *----------------------------------------------------------------------------
- */
-
- void
- Sync_UnlockAndSwitch(lockPtr, state)
- register Sync_Lock *lockPtr;
- Proc_State state;
- {
-
- MASTER_LOCK(sched_MutexPtr);
- /*
- * release the monitor lock and context switch.
- */
- lockPtr->inUse = 0;
- lockPtr->waiting = FALSE;
- SyncDeleteCurrent(lockPtr);
- SyncEventWakeupInt((unsigned int)lockPtr);
- Sched_ContextSwitchInt(state);
- #ifdef spur
- Mach_InstCountEnd(1);
- #endif
- MASTER_UNLOCK(sched_MutexPtr);
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * SyncEventWakeupInt --
- *
- * This looks through the process table for processes waiting on an
- * event. For each one it finds it clears its event and marks the
- * process runnable. Blocked processes are placed on a hash chain
- * keyed on the event they are blocked on. It is this hash chain
- * that this procedure scans.
- *
- * Results:
- * None.
- *
- * Side effects:
- * removes process table entries from their event hash chain and
- * marks them runnable.
- *
- *----------------------------------------------------------------------------
- */
-
- INTERNAL void
- SyncEventWakeupInt(event)
- unsigned int event;
- {
- register Proc_ControlBlock *procPtr;
- register Proc_PCBLink *hashChainItemPtr;
- register List_Links *chainHeader;
- register List_Links *itemPtr;
- int pnum;
-
- if (!sched_MutexPtr->value) {
- panic("SyncEventWakeupInt: master lock not held.\n");
- }
- pnum = Mach_GetProcessorNumber();
-
- sync_Instrument[pnum].numWakeupCalls++;
- chainHeader = &eventChainHeaders[event % PROC_HASHBUCKETS];
-
- itemPtr = List_First(chainHeader);
- while (!List_IsAtEnd(chainHeader, itemPtr)) {
- hashChainItemPtr = (Proc_PCBLink *)itemPtr;
- itemPtr = List_Next(itemPtr);
- procPtr = hashChainItemPtr->procPtr;
- if (procPtr->event != event) {
- sync_Collisions++;
- continue;
- }
- switch (procPtr->state) {
- case PROC_WAITING:
- break;
- case PROC_MIGRATED:
- /*
- * Need to handle waking up migrated processes.
- */
- panic("Can't handle waking up a migrated proc.\n");
- break;
- default:
- panic("%s %s",
- "Sync_EventWakeupInt:",
- "Tried to wakeup a non-waiting proc.\n");
- break;
-
- }
-
- sync_Instrument[pnum].numWakeups++;
- List_Remove((List_Links *) hashChainItemPtr);
- procPtr->event = NIL;
- if (procPtr->state == PROC_WAITING) {
- procPtr->state = PROC_READY;
- Sched_InsertInQueue(procPtr, (Proc_ControlBlock **) NIL);
- }
- }
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_WakeWaitingProcess --
- *
- * Wake up a particular process as though the local or remote event it is
- * awaiting has occurred.
- *
- * This code was originally written for a uniprocessor. As a result, the
- * case of signaling a running process was never dealt with. We must
- * prevent a running process from going to sleep in between the time
- * we see it is running, and the time it gets the signal. It would seem
- * we could do this by locking the pcb, but unfortunately
- * Sync_EventWaitInt does not grab this lock. This means we have to grab
- * the sched_MutexPtr. Ideally we would grab the mutex in the sig module
- * (Sig_Send perhaps). If we did that, then we would deadlock in this
- * routine. The bottom line is that this routine must do more than its
- * name implies, due to some weirdness in the way the system is
- * structured. If a process is ready, nothing is done. If a process
- * is running, the other processor is interrupted to force it into the
- * kernel, at which point it sees the signal.
- *
- * Results:
- * None.
- *
- * Side effects:
- * If waiting on an event, removes the given process from its event hash
- * chain and makes it runnable. If running, interrupts other processor.
- *
- *----------------------------------------------------------------------------
- */
-
- void
- Sync_WakeWaitingProcess(procPtr)
- register Proc_ControlBlock *procPtr;
- {
- MASTER_LOCK(sched_MutexPtr);
- if (procPtr->event != NIL) {
- List_Remove(&procPtr->eventHashChain.links);
- procPtr->event = NIL;
- procPtr->state = PROC_READY;
- Sched_InsertInQueue(procPtr, (Proc_ControlBlock **) NIL);
- } else if (procPtr->state == PROC_WAITING) {
- if (!(procPtr->syncFlags & SYNC_WAIT_REMOTE)) {
- panic("Sync_WakeWaitingProcess: Proc waiting but event and remote wait NIL\n");
- }
- ProcessWakeup(procPtr, procPtr->waitToken);
- } else if (procPtr->state == PROC_RUNNING &&
- procPtr->processor != Mach_GetProcessorNumber()) {
- Mach_CheckSpecialHandling(procPtr->processor);
- }
- #ifdef spur
- if (Mach_InstCountIsOn(1)) {
- panic("About to unlock sched_Mutex with inst count on.\n");
- }
- #endif
- MASTER_UNLOCK(sched_MutexPtr);
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_RemoveWaiter --
- *
- * Remove a process from any event chain it may be on.
- * This is distinguished from Sync_WakeWaitingProcess because
- * it does not place the process in the ready queue.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------------
- */
-
- void
- Sync_RemoveWaiter(procPtr)
- register Proc_ControlBlock *procPtr;
- {
- MASTER_LOCK(sched_MutexPtr);
- if (procPtr->event != NIL) {
- List_Remove(&procPtr->eventHashChain.links);
- procPtr->event = NIL;
- } else {
- if (procPtr->state == PROC_WAITING) {
- if (!(procPtr->syncFlags & SYNC_WAIT_REMOTE)) {
- panic("Sync_RemoveWaiter: Proc waiting but event and remote wait NIL\n");
- }
- procPtr->syncFlags |= SYNC_WAIT_COMPLETE;
- }
- }
- MASTER_UNLOCK(sched_MutexPtr);
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * SyncEventWaitInt --
- *
- * Make a process sleep waiting for an event. The blocked process is
- * placed on a hash chain keyed on the event. This routine will return
- * without putting the process to sleep if there is a signal pending
- * and the proper flag is set in the proc table.
- *
- * Results:
- * TRUE if woke up because of a signal, FALSE otherwise.
- *
- * Side effects:
- * The event that the process is waiting for is noted in the process
- * table. The process is marked as waiting and a new process
- * is selected to run.
- *
- *----------------------------------------------------------------------------
- */
-
- INTERNAL Boolean
- SyncEventWaitInt(event, wakeIfSignal)
- unsigned int event; /* Event to wait on. */
- Boolean wakeIfSignal; /* TRUE => wake if signal. */
- {
- Proc_ControlBlock *procPtr;
- List_Links *chainHeader;
-
- procPtr = Proc_GetCurrentProc();
-
- if (wakeIfSignal && Sig_Pending(procPtr)) {
- return(TRUE);
- }
-
- chainHeader = &eventChainHeaders[event % PROC_HASHBUCKETS];
- List_Insert(&procPtr->eventHashChain.links, LIST_ATREAR(chainHeader));
-
- procPtr->event = event;
- Sched_ContextSwitchInt(PROC_WAITING);
- return(FALSE);
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_GetWaitToken --
- *
- * Return the process id and increment and return wait token for the
- * current process.
- *
- * Results:
- * process ID and wait token for current process.
- *
- * Side effects:
- * Wait token incremented.
- *
- *----------------------------------------------------------------------------
- */
-
- ENTRY void
- Sync_GetWaitToken(pidPtr, tokenPtr)
- Proc_PID *pidPtr; /* If non-nil pid of current process. */
- int *tokenPtr; /* Wait token of current process. */
- {
- register Proc_ControlBlock *procPtr;
-
- procPtr = Proc_GetCurrentProc();
-
- MASTER_LOCK(sched_MutexPtr);
-
- procPtr->waitToken++;
- if (pidPtr != (Proc_PID *) NIL) {
- *pidPtr = procPtr->processID;
- }
- *tokenPtr = procPtr->waitToken;
-
- MASTER_UNLOCK(sched_MutexPtr);
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_SetWaitToken --
- *
- * Set the wait token for the given process. Only exists for process
- * migration should not be used in general.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Wait token value set in the PCB for the given process.
- *
- *----------------------------------------------------------------------------
- */
-
- ENTRY void
- Sync_SetWaitToken(procPtr, waitToken)
- Proc_ControlBlock *procPtr; /* Process to set token for. */
- int waitToken; /* Token value. */
- {
- MASTER_LOCK(sched_MutexPtr);
-
- procPtr->waitToken = waitToken;
-
- MASTER_UNLOCK(sched_MutexPtr);
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_ProcWait --
- *
- * This is called to block a process after it has been told by a
- * remote host that it has to wait. The wait completed flag is
- * checked here to see if the remote host's wakeup message has raced
- * (and won) with this process's decision to call this procedure.
- *
- * For safety, this routine should be expanded to automatically
- * set up a timeout event which will wake up the process anyway.
- *
- * Results:
- * TRUE if woke up because of a signal, FALSE otherwise.
- *
- * Side effects:
- * The wait complete flag of the process is checked and the process
- * is blocked if a notify message has not already arrived.
- *
- *----------------------------------------------------------------------------
- */
-
- ENTRY Boolean
- Sync_ProcWait(lockPtr, wakeIfSignal)
- Sync_Lock *lockPtr; /* If non-nil release this lock before going to
- * sleep and reaquire it after waking up. */
- Boolean wakeIfSignal; /* TRUE => Don't go to sleep if a signal is
- * pending. */
- {
- register Proc_ControlBlock *procPtr;
- Boolean releasedLock = FALSE;
- Boolean sigPending = FALSE;
-
- MASTER_LOCK(sched_MutexPtr);
- procPtr = Proc_GetCurrentProc();
- if (!(procPtr->syncFlags & SYNC_WAIT_COMPLETE)) {
- if (wakeIfSignal && Sig_Pending(procPtr)) {
- /*
- * Check for signals. If a signal is pending, then bail out.
- */
- sigPending = TRUE;
- } else {
- /*
- * Block the process. The wakeup message from the remote host
- * has not arrived.
- */
- procPtr->syncFlags |= SYNC_WAIT_REMOTE;
- if (lockPtr != (Sync_Lock *) NIL) {
- /*
- * We were given a monitor lock to release, so release it.
- */
- lockPtr->inUse = 0;
- lockPtr->waiting = FALSE;
- SyncEventWakeupInt((unsigned int)lockPtr);
- releasedLock = TRUE;
- }
- Sched_ContextSwitchInt(PROC_WAITING);
- if (wakeIfSignal && Sig_Pending(procPtr)) {
- sigPending = TRUE;
- }
- }
- }
- /*
- * After being notified (and context switching back to existence),
- * or if we have already been notified, clear state about the
- * remote wait. This means our caller should get a new token
- * (ie. retry whatever remote operation it was) before waiting
- * again.
- */
- procPtr->waitToken++;
- procPtr->syncFlags &= ~(SYNC_WAIT_COMPLETE | SYNC_WAIT_REMOTE);
- #ifdef spur
- Mach_InstCountEnd(1);
- #endif
- MASTER_UNLOCK(sched_MutexPtr);
- if (releasedLock) {
- (void) Sync_GetLock(lockPtr);
- }
- return(sigPending);
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * Sync_ProcWakeup --
- *
- * Wakeup a blocked process in response to a message from a remote
- * host. Call internal routine to do the work.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------------
- */
-
- ENTRY void
- Sync_ProcWakeup(pid, token)
- Proc_PID pid; /* PID of process to wake up. */
- int token; /* Token to use to wake up process. */
- {
- Proc_ControlBlock *procPtr;
-
- procPtr = Proc_GetPCB(pid);
- if (procPtr != (Proc_ControlBlock *)NIL) {
- MASTER_LOCK(sched_MutexPtr);
- ProcessWakeup(procPtr, token);
- MASTER_UNLOCK(sched_MutexPtr);
- }
- }
-
-
- /*
- *----------------------------------------------------------------------------
- *
- * ProcessWakeup --
- *
- * Wakeup a blocked process in response to a message from a remote
- * host. It is possible that the wakeup message has raced and
- * won against the local process's call to Sync_ProcWait. This
- * protected against with a token and a wakeup complete flag.
- * (The token provides extra protection against spurious wakeups.
- * As we don't make any guarantees about the correctness of a
- * wakeup anyway, we ignore the token here.)
- *
- * Results:
- * None.
- *
- * Side effects:
- * syncFlags modified.
- *
- *----------------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static INTERNAL void
- ProcessWakeup(procPtr, waitToken)
- register Proc_ControlBlock *procPtr; /* Process to wake up.*/
- int waitToken; /* Token to use. Now
- * this is ignored. */
- {
- procPtr->syncFlags |= SYNC_WAIT_COMPLETE;
- if (procPtr->state == PROC_WAITING) {
- /*
- * Only wakeup if are doing a 'process wait' and not an 'event wait'.
- */
- if (procPtr->event == NIL) {
- procPtr->state = PROC_READY;
- Sched_InsertInQueue(procPtr, (Proc_ControlBlock **) NIL);
- }
- } else {
- /*
- * This is a notify message which has raced (and won) with the
- * process's call to Sync_ProcWait.
- */
- syncProcWakeupRaces++;
- }
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Sync_RemoteNotify --
- *
- * Perform an RPC to notify a remote process.
- *
- * Results:
- * The return code from the RPC. This enables the caller to decide
- * if it should wait and retry the notify later if the remote
- * host is unavailable.
- *
- * Side effects:
- * This results in a call to Sync_ProcWakeup on the host of the
- * waiting process.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Sync_RemoteNotify(waitPtr)
- Sync_RemoteWaiter *waitPtr; /* Arguments to remote notify. */
- {
- Rpc_Storage storage;
- ReturnStatus status;
-
- storage.requestParamPtr = (Address)waitPtr;
- storage.requestParamSize = sizeof(Sync_RemoteWaiter);
- storage.requestDataSize = 0;
- storage.replyParamSize = 0;
- storage.replyDataSize = 0;
- status = Rpc_Call(waitPtr->hostID, RPC_REMOTE_WAKEUP, &storage);
- return(status);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Sync_RemoteNotifyStub --
- *
- * The service stub for the remote wakeup RPC.
- *
- * Results:
- * SUCCESS.
- *
- * Side effects:
- * A call to Sync_ProcWakeup on the process.
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- ReturnStatus
- Sync_RemoteNotifyStub(srvToken, clientID, command, storagePtr)
- ClientData srvToken; /* Handle on server process passed to
- * Rpc_Reply. */
- int clientID; /* Sprite ID of client host (ignored). */
- int command; /* Command identifier (ignored). */
- Rpc_Storage *storagePtr; /* The request fields refer to the request
- * buffers and also indicate the exact amount
- * of data in the request buffers. The reply
- * fields are initialized to NIL for the
- * pointers and 0 for the lengths. This can
- * be passed to Rpc_Reply. */
- {
- register Sync_RemoteWaiter *waitPtr;
-
- waitPtr = (Sync_RemoteWaiter *)storagePtr->requestParamPtr;
- Sync_ProcWakeup(waitPtr->pid, waitPtr->waitToken);
- Rpc_Reply(srvToken, SUCCESS, storagePtr, (int (*) ()) NIL,
- (ClientData) NIL);
- return(SUCCESS);
- }
-
-